/**
 * Project Name:mauto-web
 * File Name:ApiJsDicController.java
 * Package Name:com.inftech.mauto.jy.web.jsPad
 * Date:2017年6月16日下午3:01:48
 * Copyright (c) 2017, inf-technology Co., Ltd. All Rights Reserved.
 *
*/

package com.inftech.mauto.jy.web.jsPad;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ConnectException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.inftech.mauto.common.base.BaseController;
import com.inftech.mauto.common.base.BusinessException;
import com.inftech.mauto.common.constant.HttpStatusCodeEnum;
import com.inftech.mauto.common.pay.ClientCustomSSL;
import com.inftech.mauto.common.pay.HttpUtil;
import com.inftech.mauto.common.pay.PayCommonUtil;
import com.inftech.mauto.common.pay.XMLUtil;
import com.inftech.mauto.jy.entity.JyOrder;
import com.inftech.mauto.jy.service.JyOrderService;
import com.mingsoft.weixin.dao.IWeixinDao;
import com.mingsoft.weixin.entity.WeixinEntity;

/**
 * ClassName:ApiJsDicController <br/>
 * Function: 微信支付接口 <br/>
 * Date: 2017年6月16日 下午3:01:48 <br/>
 * 
 * @author hx
 * @version
 * @since JDK 1.7
 */
@Controller
@RequestMapping(value = "/api/js/wxPay", produces = "application/json;charset=utf-8")
public class ApiWxPayController extends BaseController {

	Log log = LogFactory.getLog(ApiWxPayController.class);

	private static final String WXNATIVE_NOTIFY_URL = "";// 扫码支付回调地址
	private static final String WXNATIVE_UFDODER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
	private static final String MICROPAY_URL = "https://api.mch.weixin.qq.com/pay/micropay";
	private static final String QUERY_URL = "https://api.mch.weixin.qq.com/pay/orderquery";

	@Autowired
	private IWeixinDao weixinDao;

	@Resource
	private JyOrderService jyOrderServiceImpl;

	/**
	 * 
	 * wxNative:微信扫码支付. <br/>
	 *
	 * @author Administrator
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 * @since JDK 1.7
	 */
	@RequestMapping(value = "/nativePay")
	@ResponseBody
	public String nativePay(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String outJson = "";
		try {
			String trade_type = "NATIVE";
			String orderCode = request.getParameter("orderCode");
			WeixinEntity weixin = weixinDao.getEntity(null, null, null);
			String out_trade_no = orderCode + "_" + System.currentTimeMillis();
			Map<String, Object> map1 = new HashMap<String, Object>();
			map1.put("orderCode", orderCode);
			JyOrder jyOrder = jyOrderServiceImpl.getOrderDetail(map1);
			if (jyOrder != null) {

				String nonce_str = PayCommonUtil.getNoncestr();

				String order_price = Double.parseDouble(jyOrder.getPaySum()) * 100 + "";
				List<Map<String, Object>> wxxmDetailList = jyOrderServiceImpl.getWxxmDetail(map1);

				String body = "购买项目" + wxxmDetailList.size() + "件,共" + order_price + "元";

				String pay_ip = PayCommonUtil.localIp();
				SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
				packageParams.put("appid", weixin.getWeixinAppID());
				packageParams.put("mch_id", weixin.getWeixinPayMchId());
				packageParams.put("nonce_str", nonce_str);
				packageParams.put("body", body);
				packageParams.put("out_trade_no", out_trade_no);
				packageParams.put("total_fee", order_price);
				packageParams.put("spbill_create_ip", pay_ip);
				packageParams.put("notify_url", WXNATIVE_NOTIFY_URL);
				packageParams.put("trade_type", trade_type);

				String sign = PayCommonUtil.createSign("UTF-8", packageParams, weixin.getWeixinPayKey());
				packageParams.put("sign", sign);

				String requestXML = PayCommonUtil.getRequestXml(packageParams);
				System.out.println(requestXML);

				String resXml = HttpUtil.postData(WXNATIVE_UFDODER_URL, requestXML);

				Map<String, String> map = XMLUtil.doXMLParse(resXml);
				if (map.get("return_code").equals("SUCCESS") && map.get("result_code").equals("SUCCESS")) {
					String urlCode = (String) map.get("code_url");
					HttpStatusCodeEnum statusCode = HttpStatusCodeEnum.STATUS_CODE_200;
					Map<String, Object> resultMap = new HashMap<String, Object>();
					resultMap.put("urlCode", urlCode);
					outJson = getOutJson(statusCode, true, statusCode.toString(), resultMap);
				} else {
					HttpStatusCodeEnum statusCode = HttpStatusCodeEnum.STATUS_CODE_708;
					outJson = getOutJson(statusCode, false,map.get("return_msg"), null);
				}
			} else {
				log.error("查不到订单");
				throw new NullPointerException("查不到订单");
			}
		} catch (Exception e) {
			if (e instanceof BusinessException) {
				throw e;
			}
			LOG.error("支付失败", e);
			HttpStatusCodeEnum statusCode = HttpStatusCodeEnum.SCOPE_BASE;
			outJson = getOutJson(statusCode, false, statusCode.toString(), null);
		}
		return outJson;
	}

	/**
	 * 扫码支付回调 nativePayNotify:(这里用一句话描述这个方法的作用). <br/>
	 *
	 * @author Administrator
	 * @param request
	 * @param response
	 * @throws Exception
	 * @since JDK 1.7
	 */
	@RequestMapping(value = "/nativePayNotify")
	@ResponseBody
	public void nativePayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 读取参数
		InputStream inputStream;
		StringBuffer sb = new StringBuffer();
		inputStream = request.getInputStream();
		String s;
		BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
		while ((s = in.readLine()) != null) {
			sb.append(s);
		}
		in.close();
		inputStream.close();

		// 解析xml成map
		Map<String, String> m = new HashMap<String, String>();
		m = XMLUtil.doXMLParse(sb.toString());

		// 过滤空 设置 TreeMap
		SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
		Iterator it = m.keySet().iterator();
		while (it.hasNext()) {
			String parameter = (String) it.next();
			String parameterValue = m.get(parameter);
			String v = "";
			if (null != parameterValue) {
				v = parameterValue.trim();
			}
			packageParams.put(parameter, v);
		}

		// 账号信息
		WeixinEntity weixin = weixinDao.getEntity(null, null, null);
		String payKey = weixin.getWeixinPayKey();

		log.info(packageParams);
		// 判断签名是否正确
		if (PayCommonUtil.isTenpaySign("UTF-8", packageParams, payKey)) {
			String resXml = "";
			if ("SUCCESS".equals((String) packageParams.get("result_code"))) {
				// 这里是支付成功
				String attach = (String) packageParams.get("attach");
				Map<String, Object> map = new HashMap<String, Object>();
				map.put("orderCode", attach);
				jyOrderServiceImpl.updatePayStatusByOrderCode(map);
				log.info("支付成功");
				// 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
				resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
						+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";

			} else {
				log.info("支付失败,错误信息：" + packageParams.get("err_code"));
				resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
						+ "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
			}
			BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
			out.write(resXml.getBytes());
			out.flush();
			out.close();
		} else {
			log.info("通知签名验证失败");
		}

	}

	/**
	 * 
	 * scanPay:刷卡支付. <br/>
	 *
	 * @author Administrator
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 * @since JDK 1.7
	 */
	@RequestMapping(value = "/scanPay")
	@ResponseBody
	public String scanPay(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String outJson = "";
		try {
			String orderCode = request.getParameter("orderCode");
			String auth_code = request.getParameter("authCode");
			WeixinEntity weixin = weixinDao.getEntity(null, null, null);

			String out_trade_no = orderCode + "_" + System.currentTimeMillis();
			Map<String, Object> map2 = new HashMap<String, Object>();
			map2.put("orderCode", orderCode);
			JyOrder jyOrder = jyOrderServiceImpl.getOrderDetail(map2);
			if (jyOrder != null) {

				String appid = weixin.getWeixinAppID();
				String mch_id = weixin.getWeixinPayMchId();
				String nonce_str = PayCommonUtil.getNoncestr();
				String total_fee = Double.parseDouble(jyOrder.getPaySum()) * 100 + "";
				List<Map<String, Object>> wxxmDetailList = jyOrderServiceImpl.getWxxmDetail(map2);
				String body = "购买项目" + wxxmDetailList.size() + "件,共" + total_fee + "元";

				String device_info = jyOrder.getJsId();
				String detail = "";
				String attach = orderCode;
				String spbill_create_ip = PayCommonUtil.localIp();

				SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
				packageParams.put("appid", appid);
				packageParams.put("mch_id", mch_id);
				packageParams.put("device_info", device_info);
				packageParams.put("nonce_str", nonce_str);
				packageParams.put("body", body);
				packageParams.put("detail", detail);
				packageParams.put("attach", attach);
				packageParams.put("out_trade_no", out_trade_no);
				packageParams.put("total_fee", total_fee);
				packageParams.put("spbill_create_ip", spbill_create_ip);
				packageParams.put("auth_code", auth_code);
				String sign = PayCommonUtil.createSign("UTF-8", packageParams, weixin.getWeixinPayKey());
				packageParams.put("sign", sign);

				String requestXML = PayCommonUtil.getRequestXml(packageParams);
				Map<String, String> map1 = null;
				try {
					String resXml = HttpUtil.postData(MICROPAY_URL, requestXML);
					map1 = XMLUtil.doXMLParse(resXml);
				} catch (ConnectException ce) {
					System.out.println("连接超时：" + ce.getMessage());
				} catch (Exception e) {
					System.out.println("https请求异常：" + e.getMessage());
				}
				String transaction_id = map1.get("transaction_id");

				int querycount = 10;
				boolean booleanquery = false;
				while (querycount > 0) {
					if (orderQuery(out_trade_no, transaction_id) != true && querycount > 0) {
						querycount = querycount - 1;
						booleanquery = false;
					} else {
						querycount = 0;
						booleanquery = true;
					}
					Thread.sleep(500);
				}
				if (booleanquery == false && querycount == 0) {
					// wechatcancel.ordercancel(qd);
					HttpStatusCodeEnum statusCode = HttpStatusCodeEnum.STATUS_CODE_708;
					outJson = getOutJson(statusCode, false, "获取不到订单支付状态", null);
				} else {
					jyOrderServiceImpl.updatePayStatusByOrderCode(map2);
					HttpStatusCodeEnum statusCode = HttpStatusCodeEnum.STATUS_CODE_200;
					outJson = getOutJson(statusCode, true, statusCode.toString(), null);
				}
			} else {
				log.error("查不到订单");
				throw new NullPointerException("查不到订单");
			}
		} catch (Exception e) {
			if (e instanceof BusinessException) {
				throw e;
			}
			LOG.error("支付确认失败", e);
			HttpStatusCodeEnum statusCode = HttpStatusCodeEnum.SCOPE_BASE;
			outJson = getOutJson(statusCode, false, statusCode.toString(), null);
		}
		return outJson;
	}

	/**
	 * 
	 * orderQuery:查询订单. <br/>
	 *
	 * @author Administrator
	 * @param out_trade_no
	 * @param transaction_id
	 * @return
	 * @throws Exception
	 * @since JDK 1.7
	 */
	public boolean orderQuery(String out_trade_no, String transaction_id) throws Exception {
		int successcode = 0; // 0 success 1 fail
		String nonce_str = PayCommonUtil.getNoncestr();
		WeixinEntity weixin = weixinDao.getEntity(null, null, null);
		String appid = weixin.getWeixinAppID();
		String mch_id = weixin.getWeixinPayMchId();
		SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
		packageParams.put("appid", appid);
		packageParams.put("mch_id", mch_id);
		packageParams.put("nonce_str", nonce_str);
		packageParams.put("out_trade_no", out_trade_no);
		packageParams.put("transaction_id", transaction_id);
		String sign = PayCommonUtil.createSign("UTF-8", packageParams, weixin.getWeixinPayKey());
		packageParams.put("sign", sign);
		String requestXML = PayCommonUtil.getRequestXml(packageParams);
		Map<String, String> map1 = null;
		try {
			String resXml = HttpUtil.postData(QUERY_URL, requestXML);
			map1 = XMLUtil.doXMLParse(resXml);
			System.out.println(map1.get("result_code"));
		} catch (ConnectException ce) {
			System.out.println("连接超时：" + ce.getMessage());
		} catch (Exception e) {
			System.out.println("https请求异常：" + e.getMessage());
		}
		if (map1.get("return_code").equals("SUCCESS") && map1.get("result_code").equals("SUCCESS")) {
			if (map1.get("trade_state").equals("SUCCESS")) {
				successcode = 0;
			} else if (map1.get("trade_state").equals("USERPAYING")) {
				successcode = 1;
			}
		} else {
			successcode = 1;
		}
		if (successcode == 0) {
			return true;
		} else {
			return false;
		}

	}

	/**
	 * 
	 * ordercancel:撤销订单. <br/>
	 *
	 * @author Administrator
	 * @param out_trade_no
	 * @param transaction_id
	 * @throws Exception
	 * @since JDK 1.7
	 */
	public void ordercancel(String out_trade_no, String transaction_id) throws Exception {
		WeixinEntity weixin = weixinDao.getEntity(null, null, null);
		String appid = weixin.getWeixinAppID();
		String mch_id = weixin.getWeixinPayMchId();
		SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
		String nonce_str = PayCommonUtil.getNoncestr();
		Map<Object, String> map = new TreeMap<Object, String>();
		map.put("appid", appid);
		map.put("mch_id", mch_id);
		map.put("out_trade_no", out_trade_no);
		map.put("transaction_id", transaction_id);
		map.put("nonce_str", nonce_str);
		String sign = PayCommonUtil.createSign("UTF-8", packageParams, weixin.getWeixinPayKey());
		packageParams.put("sign", sign);
		String requestXML = PayCommonUtil.getRequestXml(packageParams);
		ClientCustomSSL clientCustomSSL = new ClientCustomSSL();
		clientCustomSSL.clientcustomSSL(requestXML);

	}

}
